package com.example.spring3cities.dao;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.example.spring3cities.model.City;
import com.example.spring3cities.service.CityService;

@Repository
public class CityDao {	
	@Autowired
	private CityService cityService;
	
	@PersistenceContext
	private EntityManager entityManager;
	
	@SuppressWarnings("unchecked")
	public List<City> getCities(int limit) {
		javax.persistence.Query query = entityManager.createQuery("from City order by population desc");
		query.setMaxResults(limit);
		return query.getResultList();
	}
	
	@Transactional
	public void addCity(City city) {
		entityManager.merge(city);
	}
	
	@Transactional
	public Boolean deleteCityById(int id) {
		City cityToDelete = cityService.findCityById( this.getCities(Integer.MAX_VALUE), id);
		if(cityToDelete != null) {
			entityManager.remove(cityToDelete);
			return true;
		}
		return false;
	}
	
	@SuppressWarnings("unchecked")
	public List<City> searchCity(String term) {
		return entityManager.createQuery("from City where Name like '" + term + "%'").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<String> searchCityName(String term) {
		return entityManager.createQuery("select name from City where Name like '" + term + "%' order by Population desc").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	@Transactional
	public List<String> searchSimilarCities(String term) {
		FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
		QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(City.class).get();
		Query luceneQuery = qb.keyword().fuzzy().onField("name").matching(term).createQuery();
		
		FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, City.class);
		List<City> cities = fullTextQuery.getResultList();
		
		// Wir benötigen nur die Städtenamen und nicht das gesamte Objekt
		List<String> citynames = new ArrayList<String>();
		
		for(City currentCity: cities) {
			citynames.add(currentCity.getName());
		}
		
		fullTextEntityManager.close();
		return citynames;
	}

	public void createSearchIndex() throws InterruptedException {
		FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
		fullTextEntityManager.createIndexer(City.class).startAndWait();
		fullTextEntityManager.close();
	}
}
